package com.batyuta.sort;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 *
 */
public class MergeThreadSort extends AbstractMergeThread<MergeQueueItem> implements Runnable {
    private static Logger logger = Logger.getLogger(MergeThreadSort.class);

    public MergeThreadSort(Queue<MergeQueueItem> queueIn, Queue<MergeQueueItem> queueOut, CountDownLatch startSignal, CountDownLatch doneSignal) {
        super(queueIn, queueOut, startSignal, doneSignal);
    }

    @Override
    public MergeQueueItem process() {
        getLogger().info(this.getClass().getName() + "(" + getId() + "): start");
        MergeQueueItem result;
        while (null != (result = poll())) {
            getLogger().info(this.getClass().getName() + "(" + getId() + "): " + result.toString());
            sort(result);
            addToQueue(result);
        }
        if (null != currentQueue) {
            add(currentQueue);
        }
        return result;
    }

    @Override
    Logger getLogger() {
        return logger;
    }

    public static void sort(MergeQueueItem result) {
        File inputFile = result.getFileFirst(), outputFile = result.getFileOut();

        LineIterator lineIterator = null;
        try {
            List<String> inputData = FileUtils.readLines(inputFile);
            inputData = mergeSortRecursive(inputData);
            FileUtils.writeLines(outputFile, inputData);
        } catch (IOException e) {
            logger.error(e, e);
        } finally {
            LineIterator.closeQuietly(lineIterator);
        }
    }

    // TODO: don't use recursion
    @Deprecated
    public static List<String> mergeSortRecursive(List<String> list) {
        if (list.size() < 2) {
            return list;
        }
        List<String> listFirst = mergeSortRecursive(list.subList(0, list.size() / 2));
        List<String> listSecond = mergeSortRecursive(list.subList(list.size() / 2, list.size()));

        return mergeSort(listFirst, listSecond);
    }

    public static List<String> mergeSort(List<String> listFirst, List<String> listSecond) {
        List<String> result = new LinkedList<String>();

        Iterator<String> iteratorFirst = listFirst.iterator();
        Iterator<String> iteratorSecond = listSecond.iterator();
        String myStringFirst = getNextString(iteratorFirst);
        String myStringSecond = getNextString(iteratorSecond);
        while (null != myStringFirst && null != myStringSecond) {
            if (myStringFirst.compareTo(myStringSecond) == 0) {
                result.add(myStringFirst);
                result.add(myStringSecond);
                myStringFirst = getNextString(iteratorFirst);
                myStringSecond = getNextString(iteratorSecond);
            } else if (myStringFirst.compareTo(myStringSecond) < 0) {
                result.add(myStringFirst);
                myStringFirst = getNextString(iteratorFirst);
            } else if (myStringFirst.compareTo(myStringSecond) > 0) {
                result.add(myStringSecond);
                myStringSecond = getNextString(iteratorSecond);
            }
        }

        while (null != myStringFirst) {
            result.add(myStringFirst);
            myStringFirst = getNextString(iteratorFirst);
        }
        while (null != myStringSecond) {
            result.add(myStringSecond);
            myStringSecond = getNextString(iteratorSecond);
        }
        return result;
    }


}
